// const { xml } = require('cheerio');
const { Service } = require('egg')
const fs = require('fs')
// 解析xml的调用包
const xml2js = require('xml2js')

module.exports = class TreeService extends Service {
  /**
   * * 班级  学期 —— 学院 —— 年级 —— 专业 —— 班级
   * @return {Object} *
   */
  async class_() {
    const Cookie = this.ctx.state.Cookie
    const { term } = this.ctx.data
    const [xn, ,] = term ? term.split('-') : ['', '', '']
    const apiUrl = `${this.ctx.state.baseUrl}/cssfjw/frame/droplist/getDropLists.action`
    const res = await this.ctx.curl(apiUrl, {
      method: 'POST',
      headers: {
        Cookie,
        // Referer: 'http://58.20.34.197:10115/cssfjw/kbbp/dykb.jskb.html?menucode=SB02',
        'Content-Type': 'application/x-www-form-urlencoded',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36',
      },
      data: {
        comboBoxName: 'MsYXB',
        paramValue: `nj=${xn}`,
        isYXB: '0',
        isCDDW: '0',
        isXQ: '0',
        isDJKSLB: '0',
        isZY: '0',
      },
      timeout: 10000,
    })
    const tree = {
      [term]: [],
    }
    if (res.status === 200) {
      try {
        const data = JSON.parse(res.data.toString())
        // const teacherList = []
        // 学院列表
        const xyList = []
        data.forEach(async (item) => {
          xyList.push({
            value: item.code,
            label: item.name.replace(/\[.*\]/g, ''),
            children: [],
          })
        })
        xyList.sort((a, b) => a.label.length - b.label.length)

        /* 根据学期构造年级 (4个) */
        const njList = []
        for (let i = 0; i < 4; i++) {
          const value = `${Number(term.split('-')[0] - i)}`
          njList.push({
            value,
            label: value,
            children: [],
          })
        }
        // 将学院列表的子列表中插入四个学期对象，作为子列表的元素
        xyList.forEach((item) => {
          njList.forEach((nj) => {
            /**
             * * 为什么不直接保存nj，因为nodejs中是地址引用，而不是内容引用，在后续向表格添加内容的时候，会产生数据共通的神奇现象。
             * */
            item.children.push({
              value: nj.value,
              label: nj.label,
              children: [],
            })
          })
        })

        // 专业情况访问-professionalSituationAccessCollection-pSAC
        const pSAC = []

        // 遍历学院列表，依照其学院value和子列表中学期value，访问网页，获取专业列表，并插入到子列表中
        for (const xy of xyList) {
          for (const nj of xy.children)
          {
            // 发送请求;
            const Url = 'http://58.20.34.197:10115/cssfjw/frame/droplist/getDropLists.action'
            const query = this.ctx.curl(Url, {
              method: 'POST',
              headers: {
                Cookie,
                // Referer: 'http://58.20.34.197:10115/cssfjw/kbbp/dykb.jskb.html?menucode=SB02',
                'Content-Type': 'application/x-www-form-urlencoded',
                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36',
              },
              data: {
                comboBoxName: 'MsYXB_Specialty',
                paramValue: `nj=${nj.value}&dwh=${xy.value}`,
                isYXB: '0',
                isCDDW: '0',
                isXQ: '0',
                isDJKSLB: '0',
                isZY: '0',
              },
              timeout: 10000,
            })
            pSAC.push(query)
          }
        }

        // 专业情况访问结果集合-professionalSituationAccessResultsCollection-pSARC
        const pSARC = await Promise.all(pSAC)
        let index = 0
        for (let i = 0; i < xyList.length; i++) {
          for (let j = 0; j < xyList[i].children.length; j++) {
            const temD = JSON.parse(pSARC[index++].data.toString())
            if (temD.length !== 0) {
              // 用重新定义变量的方式打破地址引用所产生的连锁反应
              const zyList = temD.map((e) => ({
                value: e.code,
                label: e.name.replace(/\[.*\]/g, ''),
                children: [],
              }))
              zyList.sort((a, b) => a.label.length - b.label.length)
              xyList[i].children[j].children = zyList
            }
          }
        }

        // 班级情况访问-classVisits-cV
        for (const xy of xyList) {
          for (const nj of xy.children) {
            for (const zy of nj.children) {
              const url = `${this.ctx.state.baseUrl}/cssfjw/taglib/CombBoxServlet.jsp`
              const res = await this.ctx.curl(url, {
                method: 'POST',
                headers: {
                  Cookie,
                  Referer: 'http://58.20.34.197:10115/cssfjw/kbbp/dykb.jskb.html?menucode=SB02',
                  'Content-Type': 'application/x-www-form-urlencoded',
                  'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36',
                },
                data: {
                  className: 'kbbp_dykb_SpecialClassComb',
                  loadDataStyle: 'loadClass',
                  xn,
                  xq_m: '1',
                  nj: `${nj.value}`,
                  yxb: `${xy.value}`,
                  zy: `${zy.value}`,
                  flag: '',
                  xqdm: '',
                },
                timeout: 10000,
              })
              if (res.data) {
                // console.log('1', 1);
                const xmlData = res.data.toString()
                // console.log('xmlData', xmlData);
                const bjList = []
                if (xmlData !== '') {
                // xml解析函数是一个异步函数，需要等他解析完再进行下一步，用await控制
                // eslint-disable-next-line no-loop-func
                  await xml2js.parseStringPromise(xmlData).then((result) => {
                  // 初始化一个空对象来保存所有的内容
                    let values = { value: '', label: '' }
                    // 遍历所有的 info 元素
                    for (const ind in result.data.info) {
                      values.value = result.data.info[ind].value[0]
                      values.label = result.data.info[ind].fillName[0].replace(/\[.*\]/g, '').replace(/\（/g, '\(').replace(/\）/g, '\)')
                      bjList.push(values)
                      values = { value: '', label: '' }
                    }
                    bjList.sort((a, b) => a.label.length - b.label.length)
                    // 楼层列表的子列表赋值
                    zy.children = bjList
                  }).catch((err) => {
                    console.error('Error parsing XML:', err)
                  })
                }
              }
            }
          }
        }

        tree[term] = xyList

        /* 储存 */
        const filePath = './app/public/tree-class.json'
        // 判断文件是否存在
        fs.promises.access(filePath, fs.constants.F_OK)
          .then(() =>
            // 文件存在，读取文件内容
            fs.promises.readFile(filePath, 'utf-8'))
          .then((data) => {
            // 文件内容转为对象
            const jsonData = JSON.parse(data)
            jsonData[term] = xyList
            fs.writeFileSync(filePath, JSON.stringify(jsonData))
          })
          .catch((err) => {
            if (err.code === 'ENOENT') {
              fs.writeFileSync(filePath, JSON.stringify(tree))
            } else {
              console.error('读取文件出错', err)
            }
          })

        return tree
      } catch (err) {
        console.log('err', err)
        throw err
      }
    }
    return tree
  }

  /**
   * * 教师  学期 —— 学院 —— 教师
   * @return {Object} *
   */
  async teacher() {
    const Cookie = this.ctx.state.Cookie
    const { term } = this.ctx.data
    const [xn, , xqRaw] = term ? term.split('-') : ['', '', '']
    const apiUrl = `${this.ctx.state.baseUrl}/cssfjw/frame/droplist/getDropLists.action`
    const res = await this.ctx.curl(apiUrl, {
      method: 'POST',
      headers: {
        Cookie,
        // Referer: 'http://58.20.34.197:10115/cssfjw/kbbp/dykb.jskb.html?menucode=SB02',
        'Content-Type': 'application/x-www-form-urlencoded',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36',
      },
      data: {
        comboBoxName: 'MsDepartment',
        paramValue: '',
        isYXB: '0',
        isCDDW: '0',
        isXQ: '0',
        isDJKSLB: '0',
        isZY: '0',
      },
      timeout: 10000,
    })
    const tree = {
      [term]: [],
    }
    if (res.status === 200) {
      try {
        const data = JSON.parse(res.data.toString())
        // const teacherList = []
        // 学院列表
        const xyList = []
        data.forEach(async (item) => {
          xyList.push({
            value: item.code,
            label: item.name.replace(/\[.*\]/g, ''),
            children: [],
          })
        })
        xyList.sort((a, b) => a.label.length - b.label.length)

        // 教师列表
        let teacherList = []

        // 发送请求获取教师列表
        const Url = 'http://58.20.34.197:10115/cssfjw/taglib/CombBoxServlet.jsp'
        const response = []
        for (const item in xyList) {
          const query = this.ctx.curl(Url, {
            method: 'POST',
            headers: {
              Cookie,
              Referer: 'http://58.20.34.197:10115/cssfjw/kbbp/dykb.jskb.html?menucode=SB02',
              'Content-Type': 'application/x-www-form-urlencoded',
              'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36',
            },
            data: {
              className: 'jbxx_EmployeeAndTeacher',
              loadDataStyle: 'loadClass',
              xn,
              xq_m: xqRaw,
              flag: '',
              jsbm: xyList[item].value,
            },
            timeout: 20000,
          })
          response.push(query)
        }
        const resAll = await Promise.all(response)
        for (let i = 0; i < resAll.length; i++) {
          const xmlData = resAll[i].data.toString()
          // 判断数据是否为空，不为空进入解析，为空则直接返回空列表
          if (xmlData !== '') {
            // xml解析函数是一个异步函数，需要等他解析完再进行下一步，用await控制
            // eslint-disable-next-line no-loop-func
            await xml2js.parseStringPromise(xmlData).then((result) => {
              // 初始化一个空对象来保存所有的内容
              let values = { value: '', label: '' }
              // 遍历所有的 info 元素
              for (const index in result.data.info) {
                values.value = result.data.info[index].value[0]
                values.label = result.data.info[index].fillName[0].replace(/\[.*\]/g, '')
                teacherList.push(values)
                values = { value: '', label: '' }
              }
              // 对老师列表进行排序
              teacherList.sort((a, b) => a.label.length - b.label.length)
              xyList[i].children = teacherList
              teacherList = []
            }).catch((err) => {
              console.error('Error parsing XML:', err)
            })
          }
        }
        tree[term] = xyList

        /* 储存 */
        const filePath = './app/public/tree-teacher.json'
        // 判断文件是否存在
        fs.promises.access(filePath, fs.constants.F_OK)
          .then(() =>
            // 文件存在，读取文件内容
            fs.promises.readFile(filePath, 'utf-8'))
          .then((data) => {
            // 文件内容转为对象
            const jsonData = JSON.parse(data)
            jsonData[term] = xyList
            fs.writeFileSync(filePath, JSON.stringify(jsonData))
          })
          .catch((err) => {
            if (err.code === 'ENOENT') {
              fs.writeFileSync(filePath, JSON.stringify(tree))
            } else {
              console.error('读取文件出错', err)
            }
          })
        return tree
      } catch (err) {
        console.log('err', err)
        throw err
      }
    }
    return tree
  }

  /**
   * * 教室 学期 —— 校区 —— 教学楼 —— 教室
   * @return {Object} *
   */
  async classroom() {
    const Cookie = this.ctx.state.Cookie
    const { term } = this.ctx.data
    const apiUrl = `${this.ctx.state.baseUrl}/cssfjw/frame/droplist/getDropLists.action`
    const res = await this.ctx.curl(apiUrl, {
      method: 'POST',
      headers: {
        Cookie,
        'Content-Type': 'application/x-www-form-urlencoded',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36',
      },
      data: {
        comboBoxName: 'MsSchoolArea',
        paramValue: '',
        isYXB: '0',
        isCDDW: '0',
        isXQ: '0',
        isDJKSLB: '0',
        isZY: '0',
      },
      timeout: 10000,
    })
    const tree = {
      [term]: [],
    }

    if (res.status === 200) {
      try {
        const data = JSON.parse(res.data.toString())
        // 校区表格
        const xqList = []
        data.forEach((item) => {
          xqList.push({
            value: item.code,
            label: item.name,
            children: [],
          })
        })
        xqList.sort((a, b) => a.label.length - b.label.length)

        // 楼层表格
        let lcList = []
        // 楼层所有请求的集合
        const response = []
        for (const i in xqList) {
          const Url = `${this.ctx.state.baseUrl}/cssfjw/frame/droplist/getDropLists.action`
          const res = this.ctx.curl(Url, {
            method: 'POST',
            headers: {
              Cookie,
              'Content-Type': 'application/x-www-form-urlencoded',
              'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36',
            },
            data: {
              comboBoxName: 'MsSchoolArea_LF',
              paramValue: `ssxq=${xqList[i].value}`,
              isYXB: '0',
              isCDDW: '0',
              isXQ: '0',
              isDJKSLB: '0',
              isZY: '0',
            },
            timeout: 10000,
          })
          response.push(res)
        }
        const lcresAll = await Promise.all(response)
        for (let i = 0; i < lcresAll.length; i += 1) {
          const data = JSON.parse(lcresAll[i].data.toString())
          if (data.length !== 0) {
            // 构造数据列表
            // eslint-disable-next-line no-loop-func
            data.forEach((item) => {
              lcList.push({
                value: item.code,
                label: item.name,
                children: [],
              })
            })
          }
          // 楼层列表按label标签长度递增
          lcList.sort((a, b) => a.label.length - b.label.length)
          xqList[i].children = lcList

          // 获取教室信息
          let classroomTable = []
          for (let j = 0; j < lcList.length; j += 1) {
            const jsUrl = `${this.ctx.state.baseUrl}/cssfjw/taglib/CombBoxServlet.jsp`
            const res = await this.ctx.curl(jsUrl, {
              method: 'POST',
              headers: {
                Cookie,
                Referer: 'http://58.20.34.197:10115/cssfjw/kbbp/dykb.jsikb.html?menucode=SB04',
                'Content-Type': 'application/x-www-form-urlencoded',
                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36',
              },
              data: {
                className: 'jxap_combbox_js',
                loadDataStyle: 'loadClass',
                xq_m: xqList[i].value,
                jslx_m: '',
                lf_m: lcList[j].value,
                flag: 'ck',
              },
              timeout: 10000,
            })
            // 设置一个变量来保存返回的data数据
            const xmlData = res.data.toString()
            if (xmlData !== '') {
              // xml解析函数是一个异步函数，需要等他解析完再进行下一步，用await控制
              // eslint-disable-next-line no-loop-func
              await xml2js.parseStringPromise(xmlData).then((result) => {
              // 初始化一个空对象来保存所有的内容
                let values = { value: '', label: '' }
                // 遍历所有的 info 元素
                for (const index in result.data.info) {
                  values.value = result.data.info[index].value[0]
                  // 因为删除[]即其中内容会有一些地名十分诡异，所以就将不规整的括号修改一下
                  values.label = result.data.info[index].fillName[0].replace(/\（/g, '\(').replace(/\）/g, '\)')
                  classroomTable.push(values)
                  values = { value: '', label: '' }
                }
                classroomTable.sort((a, b) => a.label.length - b.label.length)
                // 楼层列表的子列表赋值
                lcList[j].children = classroomTable
              }).catch((err) => {
                console.error('Error parsing XML:', err)
              })
            } else {
              lcList[j].children = []
            }
            classroomTable = []
          }
          lcList = []
        }
        tree[term] = xqList

        /* 储存 */
        const filePath = './app/public/tree-classroom.json'
        // 判断文件是否存在
        fs.promises.access(filePath, fs.constants.F_OK).then(() =>
          // 文件存在，读取文件内容
          fs.promises.readFile(filePath, 'utf-8')).then((data) => {
          // 文件内容转为对象
          const jsonData = JSON.parse(data)
          jsonData[term] = xqList
          fs.writeFileSync(filePath, JSON.stringify(jsonData))
        }).catch((err) => {
          if (err.code === 'ENOENT') {
            fs.writeFileSync(filePath, JSON.stringify(tree))
          } else {
            console.error('读取文件出错', err)
          }
        })

        return tree
      } catch (err) {
        console.log('err', err)
        throw err
      }
    }
    return tree
  }
}
